package cn.jh.common.pay.utils;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.base.MoreObjects;
import org.jetbrains.annotations.NotNull;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * Open Api 接收请求的参数基本模型。
 *
 * @author Fuchun
 * @since 1.0
 */
public abstract class InEntity implements Serializable {

    // 分配给商户的应用id(商户号)，该参数需要参与数据签名

    /**
     * 对应 Merchant.merchantId
     */
    private String appId;

    /**
     * 发送请求的时间，该参数需要参与数据签名，格式：`yyyy-MM-dd HH:mm:ss`
     */
    private String timestamp;

    /**
     * 数据签名（Base64格式）
     */
    private String sign;

    private transient String signContent = null;

    protected InEntity() {

    }

    public void applyData(InData data) {
        this.appId = data.getAppId();
        this.timestamp = data.getTimestamp();
    }

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public String getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    @JsonIgnore
    public String getSignContent() {
        if (signContent != null) return signContent;
        List<String> parts = new ArrayList<>(12);
        parts.add(getAppId());
        applySign(parts);
        parts.add(getTimestamp());
        signContent = String.join("_", parts);
        return signContent;
    }

    protected void applySign(@NotNull final List<String> parts) {
        // implementation by sub-class
    }

    protected MoreObjects.ToStringHelper toStringHelper(Map<String, Object> map) {
        MoreObjects.ToStringHelper tsh = MoreObjects.toStringHelper(getClass())
                .add("appId", appId)
                .add("timestamp", timestamp);
        if (map != null && !map.isEmpty()) {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                tsh.add(entry.getKey(), entry.getValue());
            }
        }
        applyToString(tsh);
        tsh.add("sign", sign);
        return tsh;
    }

    protected void applyToString(MoreObjects.ToStringHelper tsh) {

    }

    @Override
    public String toString() {
        return toStringHelper(null).toString();
    }
}
